import os
from Products.MaildropHost.MaildropHost import MaildropHost
from Products.MaildropHost.MaildropHost import Email
from Products.MailHost.MailHost import MailHost
from Products.SecureMailHost.SecureMailHost import SecureMailHost
from Globals import InitializeClass
from Globals import DTMLFile
from AccessControl import ClassSecurityInfo
from Products.PageTemplates.PageTemplateFile import PageTemplateFile
import email
from BTrees.OOBTree import OOBTree
from time import time
from AccessControl.Permissions import view
from AccessControl.Permissions import change_configuration
from AccessControl.Permissions import view_management_screens
from rendering import render_raw_message
from ely.maildrophostmonster.interfaces import IMaildropHostMonster
from zope.interface import implements
from Products.MaildropHost.maildrop.stringparse import parse_assignments


class MaildropHostMonster(MaildropHost, SecureMailHost):

    implements(IMaildropHostMonster)
    security = ClassSecurityInfo()
    meta_type = 'Maildrop Host Monster'

    manage_options=(
        (MaildropHost.manage_options[0],
         {'label':'Spool',
          'action':'index_html',
          },
         {'label':'Test',
          'action':'manage_sendMailForm',
          },)
        + MaildropHost.manage_options[1:]
        )

    security.declarePrivate('__init__')
    def __init__(self, id='MailHost', title='MailHost'):
        """Initialize a new MaildropHostMonster.
        """
        MaildropHost.__init__(self, id, title)
        self._testing = self._testing_mode_default()
        self._testspool = OOBTree()

    security.declareProtected(view, 'index_html')
    index_html = PageTemplateFile('www/viewTestSpool', globals())

    security.declareProtected(view_management_screens, 'manage_sendMailForm')
    manage_sendMailForm = PageTemplateFile('www/sendMailForm', globals())

    security.declareProtected(view_management_screens, 'manage_main')
    manage_main = DTMLFile('www/manageMaildropHost', globals())

    security.declareProtected(view, 'viewMessage')
    viewMessage = PageTemplateFile('www/viewMessage', globals())

    security.declareProtected(change_configuration, 'manage_makeChanges')

    def manage_makeChanges(self, title, transactional=False, testing=False,
                          path_key=None, REQUEST=None, **ignored):
        """Change the MaildropHostMonster properties.
        """
        self._testing = not not testing
        return MaildropHost.manage_makeChanges(self, title, transactional,
                                               path_key, REQUEST)

    security.declareProtected(change_configuration, 'enableTesting')
    def enableTesting(self):
        """Enable testing mode.
        """
        self._testing = True

    security.declareProtected(view, 'isTesting')
    def isTesting(self):
        """Is testing mode in use?
        """
        return getattr(self, '_testing', True)

    security.declareProtected(view, 'renderMessage')
    def renderMessage(self, id):
        """Return a rendering of a message suitable for viewing in a browser.
        """
        if not self.isTesting():
            return None
        message = render_raw_message(self._testspool[id].body)
        return message

    security.declareProtected(view, 'listSpool')
    def listSpool(self):
        """List the contents of the maildrop spool.
        """
        if not self.isTesting():
            return None
        spool = list(self._testspool.values())
        spool.reverse()
        return spool

    security.declareProtected(view_management_screens, 'manage_send')
    def manage_send(self, body, mto, mfrom, subject, REQUEST=None):
        """Send test mail.
        """
        message = email.MIMEText.MIMEText(body)
        message['Subject'] = subject
        message['To'] = mto
        message['From'] = mfrom
        self.send(message.as_string())
        if REQUEST is not None:
            if self.isTesting():
                view = ''
            else:
                view = 'manage_sendMailForm'
            url = ('%s/%s?manage_tabs_message=Test mail sent.'
                   % (self.absolute_url(), view))
            REQUEST['RESPONSE'].redirect(url)

    security.declareProtected(view, 'clearSpool')
    def clearSpool(self, REQUEST=None):
        """Clear the test spool.
        """
        if not self.isTesting():
            return None
        self._testspool.clear()
        if REQUEST is not None:
            url = ('%s/?manage_tabs_message=Spool cleared.'
                   % self.absolute_url())
            REQUEST['RESPONSE'].redirect(url)

    security.declarePrivate('_generateId')
    def _generateSequentialId(self, container, time=time):
        timestamp = str(time())
        while container.has_key(timestamp):
            timestamp += '1'
        return timestamp

    security.declarePrivate('_send')
    def _send(self, m_from, m_to, msg, debug=False, immediate=False):
        """Send the message.
        """
        if hasattr(msg, 'as_string'):
            # For MIMEText messages.
            msg = msg.as_string()
        else:
            # For other messages.
            msg = str(msg)
        if self.isTesting():
            id = self._generateSequentialId(self._testspool)
            email = TestEmail(m_from, m_to, msg, id)
            self._testspool.insert(id, email)
            return email
        else:
            return MaildropHost._send(self, m_from, m_to, msg, immediate)

    def _testing_mode_default(self):
        config = dict(parse_assignments(open(self.getConfigPath()).read()))
        return not not config.get('TESTING_MODE_DEFAULT', False)


class TestEmail(Email):

    __allow_access_to_unprotected_subobjects__ = True

    def __init__(self, mfrom, mto, body, id):
        temp_path = None
        Email.__init__(self, mfrom, mto, body, temp_path)
        msg = email.message_from_string(self.body)
        self.subject = msg['Subject']
        self.id = id
        self.date = msg['Date']

    def __repr__(self):
        return ('<TestEmail Subject: %s, To: %s, From: %s>'
                % (self.subject, self.m_to, self.m_from))

    def __str__(self):
        return self.body


addMaildropHostMonsterForm = DTMLFile('www/addMaildropHostMonster_form',
                                      globals())

def manage_addMaildropHostMonster(self, id, title='Maildrop Host Monster',
                                  REQUEST=None):
    """Add a MaildropHostMonster into the system.
    """
    mhm = MaildropHostMonster(id, title)
    self._setObject(id, mhm)
    if REQUEST is not None:
        url = '%s/%s/manage_main' % (self.absolute_url(), id)
        REQUEST['RESPONSE'].redirect(url)

def replaceMailHost(self):
    """Replace an existing MailHost with MailDropHostMonster.
    """
    if 'MailHost' in self.objectIds():
        if not isinstance(self.MailHost, MaildropHostMonster):
            self.manage_delObjects(['MailHost'])
            manage_addMaildropHostMonster(self, 'MailHost')


InitializeClass(MaildropHostMonster)
